#ifndef PARSER_HPP
#define PARSER_HPP

#include "lexer.hpp"

class Node;
class CmpNode;
class TypeNode;
class ListNode;
class SymbolTable;
class TypeTable;

class Parser {
private:
    Lexer* _lex;
    Token* _cur_token;

    SymbolTable*    _sym_table;
    TypeTable*      _type_table;
    
public:
    Parser(Lexer* lex, SymbolTable* symtable);
    ~Parser();

    Node* parse();

    void consume();
    Token* get_token();
    void match(TokenType tt);
    
    Node* stmts();
    Node* stmt();
    Node* print_stmt();
    Node* return_stmt();
    Node* if_stmt();
    Node* code_block();
    Node* while_stmt();
    Node* var_def_stmt();
    Node* val_def_stmt();
    Node* assign_stmt(Node* left);
    Node* new_clause();

    Node* param_def();
    ListNode* parameters();
    Node* func_def();

    Node* lambda_def();
    Node* func_call();

    CmpNode* cmp_op();
    Node* expression();
    Node* or_test();
    Node* and_test();
    Node* not_test();
    Node* comparison();
    Node* or_expr();
    Node* xor_expr();
    Node* and_expr();
    Node* shift_expr();
    Node* arith_expr();
    Node* term();
    Node* factor();
    Node* atom();
    bool is_trailer_char(TokenType tt);
    Node* trails(Node* left);
    int stoi(Token* data);

    /* types */
    Node* typedef_stmt();
    Node* type_atom();
    Node* type_stmt();

    Node* type_param();
    ListNode* type_arguments();
    ListNode* type_parameters();
    ListNode* expr_list();
};

void eval(const char* s);

#endif

